package org.aeon.gamechatnest.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.aeon.gamechatnest.common.response.Result;
import org.aeon.gamechatnest.common.response.ResultBuild;
import org.aeon.gamechatnest.exception.TargetIsAnEmptyException;
import org.aeon.gamechatnest.pojo.Role;
import org.aeon.gamechatnest.pojo.RoleAuthority;
import org.aeon.gamechatnest.service.RoleService;
import org.aeon.gamechatnest.validated.Add;
import org.aeon.gamechatnest.validated.Update;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author: MissingAeon
 * @date: 2024/5/13 10:53
 * @description: 角色
 */

@Slf4j
@Tag(description = "角色相关接口", name = "RoleControllerApi")
@Validated
@RestController
@RequestMapping("/role")
public class RoleController {
    @Autowired
    private RoleService roleService;

    @PreAuthorize("hasAnyAuthority('role:find','admin','creator') AND " +
            "#serverId == T(org.aeon.gamechatnest.util.SecurityUtil).server")
    @Operation(summary = "获取服务器所有角色", description = "服务器所有角色", parameters = {
            @Parameter(name = "serverId", description = "服务器id")
    })
    @GetMapping("/{serverId}")
    public Result getRole(@PathVariable("serverId") Long serverId) {
        List<Role> roles = roleService.findByServerId(serverId);
        return ResultBuild.result().successful().data(roles).build();
    }

    @PreAuthorize("hasAnyAuthority('role:add','admin','creator') AND " +
            "#role.serverId == T(org.aeon.gamechatnest.util.SecurityUtil).server")
    @Operation(summary = "保存新角色", description = "保存新角色")
    @PostMapping
    public Result save(@RequestBody @Validated(Add.class) Role role) {
        boolean result = roleService.save(role);
        return ResultBuild.successIf(result).build();
    }

    @PreAuthorize("hasAnyAuthority('role:mod','admin','creator') AND " +
            "@roleController.getUserServerId(#role.roleId) == T(org.aeon.gamechatnest.util.SecurityUtil).server")
    @Operation(summary = "修改角色名称", description = "修改角色名称")
    @PutMapping
    public Result modifyName(@RequestBody @Validated(Update.class) Role role) {
        boolean result = roleService.modify(role);
        return ResultBuild.successIf(result).build();
    }

    @PreAuthorize("hasAnyAuthority('role:del','admin','creator') AND " +
            "@roleController.getUserServerId(#roleId) == T(org.aeon.gamechatnest.util.SecurityUtil).server")
    @Operation(summary = "删除角色", description = "删除角色", parameters = {
            @Parameter(name = "roleId", description = "角色id")
    })
    @DeleteMapping("/{roleId}")
    public Result remove(@PathVariable("roleId") Long roleId) {
        boolean result = roleService.remove(roleId);
        return ResultBuild.successIf(result).build();
    }

    @PreAuthorize("hasAnyAuthority('authority:add','admin','creator') AND " +
            "@roleController.getUserServerId(#roleAuthority.roleId) == T(org.aeon.gamechatnest.util.SecurityUtil).server")
    @Operation(summary = "保存角色新权限关系", description = "保存角色新权限关系")
    @PostMapping("/authority")
    public Result saveRoleAuthority(@RequestBody @Validated RoleAuthority roleAuthority) {
        boolean result = roleService.save(roleAuthority);
        return ResultBuild.successIf(result).build();
    }

    @PreAuthorize("hasAnyAuthority('authority:del','admin','creator') AND " +
            "@roleController.getUserServerId(#roleAuthority.roleId) == T(org.aeon.gamechatnest.util.SecurityUtil).server")
    @Operation(summary = "删除角色权限关系", description = "删除角色权限关系", parameters = {
            @Parameter(name = "roleId", description = "角色id")
    })
    @DeleteMapping("/authority")
    public Result removeRoleAuthority(@RequestBody @Validated RoleAuthority roleAuthority) {
        boolean result = roleService.remove(roleAuthority);
        return ResultBuild.successIf(result).build();
    }


    /**
     * 获取角色所在的服务器id
     * 调用后可以无需判断 roleId 是否存在
     *
     * @param roleId 角色id
     * @return 角色的服务器id
     * @throws TargetIsAnEmptyException 如果角色不存在
     */
    public Long getUserServerId(Long roleId) throws TargetIsAnEmptyException {
        return roleService.findServerIdByRoleId(roleId);
    }
}
